﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Controls.Primitives;
using System.Reflection;

namespace GoodStuff.Silverlight
{
    //public class CommandBehaviour : TriggerAction
    //{
    //    public string CommandName
    //    {
    //        get { return (string)GetValue(CommandNameProperty); }
    //        set { SetValue(CommandNameProperty, value); }
    //    }

    //    // Using a DependencyProperty as the backing store for CommandName.  This enables animation, styling, binding, etc...
    //    public static readonly DependencyProperty CommandNameProperty =
    //        DependencyProperty.Register("CommandName", typeof(string), typeof(CommandBehaviour), new PropertyMetadata(null));

    //    protected override void Invoke(object parameter)
    //    {
    //        var dc = AssociatedObject.DataContext;
    //        PropertyInfo method = dc.GetType().GetProperty(CommandName);
    //        if (method != null)
    //        {
    //            ICommand command = method.GetValue(dc, null) as ICommand;
    //            if (command != null)
    //            {
    //                if (command.CanExecute(parameter))
    //                {
    //                    command.Execute(parameter);
    //                }
    //            }
    //        }
    //    }
    //}



    /// <summary>
    /// Attached property to bind a reflectivecommand to an event.
    /// </summary>
    public class EventCommand 
    {
        public static string GetCommand(DependencyObject obj)
        {
            return (string)obj.GetValue(CommandProperty);
        }

        public static void SetCommand(DependencyObject obj, string value)
        {
            obj.SetValue(CommandProperty, value);
        }

        // Using a DependencyProperty as the backing store for EventCommand.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CommandProperty =
            DependencyProperty.RegisterAttached("Command", typeof(string), typeof(EventCommand), new PropertyMetadata(OnEventCommandChanged));


        public static object GetDataContext(DependencyObject obj)
        {
            return (object)obj.GetValue(DataContextProperty);
        }

        public static void SetDataContext(DependencyObject obj, object value)
        {
            obj.SetValue(DataContextProperty, value);
        }

        // Using a DependencyProperty as the backing store for CommandDataContext.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DataContextProperty =
            DependencyProperty.RegisterAttached("DataContext", typeof(object), typeof(EventCommand), null
            );

        private static void OnEventCommandChanged(DependencyObject target, DependencyPropertyChangedEventArgs args)
        {            
            if (target is ButtonBase)
            {
                ButtonBase button = (ButtonBase)target;
                button.Loaded += new RoutedEventHandler(button_Loaded);
            }
        }

        static void button_Loaded(object sender, RoutedEventArgs args)
        {
            ButtonBase button = (ButtonBase)sender;

            object dataContext = GetDataContext(button);
            if (dataContext == null)
            {
                dataContext = button.DataContext;
            }

            //Must wait until the datacontext has been set.
            ReflectiveCommand command = new ReflectiveCommand(dataContext, GetCommand((DependencyObject)sender));

            command.CanExecuteChanged += (s, e) => { button.IsEnabled = command.CanExecute(button.Tag); };

            ////we start with a simple click.
            button.IsEnabled = command.CanExecute(button.Tag);
            
            button.Click += (s, e) => { command.Execute(button.Tag); };
            
            //only once please.
            button.Loaded -= button_Loaded;
        }      
    }
}
